﻿# coding: utf-8

import wx
import wx.lib.colourselect as csel
import xml.dom.minidom as minixml

from wxFramework.CustomUI import wxColorPickButton

import Material
import MPAlphaBlend
import MPAlphaTest
import MPCullingMode
import MPDepthState
import MPAmbient
import MPDiffuse
import MPSpecular
import TextureMapping

class wxDialogMaterialEdit(wx.Dialog):
    def __init__(self, parent):
        wx.Dialog.__init__(self, parent, -1, title = TD.DIALOG_MATERIAL_EDIT)
        
        self._materialHandle = 0
        
        # Layout all UI.
        sizerRenderState = self.__CreateUIRenderState()
        sizerShaderConstant = self.__CreateUIShaderConstant()
        
        self._bnOK = wx.Button(self, wx.ID_OK, TD.BUTTON_OK)
        self._bnCancel = wx.Button(self, wx.ID_CANCEL, TD.BUTTON_CANCEL)
        sizerButton = wx.BoxSizer(wx.HORIZONTAL)
        sizerButton.Add(self._bnOK, 0, wx.CENTER|wx.ALL, border = 5)
        sizerButton.Add(self._bnCancel, 0, wx.CENTER|wx.ALL, border = 5)
        
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(sizerRenderState, 0, wx.ALL|wx.EXPAND, border = 5)
        sizer.Add(sizerShaderConstant, 0, wx.ALL|wx.EXPAND, border = 5)
        sizer.Add(sizerButton, 0, wx.ALL|wx.EXPAND, border = 5)
        self.SetSizer(sizer)
        self.Fit()
        self.CentreOnScreen(wx.BOTH)
        
        # bind all event.
        self._bnOK.Bind(wx.EVT_BUTTON, self.__OnBnClickOk)
        
    def __OnBnClickOk(self, e):
        if not self._materialHandle:
            self.EndModal(wx.ID_CANCEL)

       # alpha blend
        bEnableAlphaBlend = self._cbEnableAlphaBlend.GetValue()
        srcBlend = self._comboSrcBlend.GetSelection()
        destBlend = self._comboDestBlend.GetSelection()
        alphaBlendHandle = Material.GetAlphaBlendProperty(self._materialHandle)
        MPAlphaBlend.SetAlphaBlend(alphaBlendHandle, bEnableAlphaBlend, srcBlend, destBlend)
        
        # alpha test
        bEnableAlphaTest = self._cbEnableAlphaTest.GetValue()
        alphaTestType = self._comboAlphaTestType.GetSelection()
        alphaTestRef = int(self._editAlphaTestRef.GetValue())
        alphaTestHandle = Material.GetAlphaTestProperty(self._materialHandle)
        MPAlphaTest.SetAlphaTest(alphaTestHandle, bEnableAlphaTest, alphaTestType, alphaTestRef)
        
        # culling mode
        cullingMode = self._comboCullingMode.GetSelection()
        cullingModeHandle = Material.GetCullingModeProperty(self._materialHandle)
        MPCullingMode.SetCullingMode(cullingModeHandle, cullingMode)
        
        # depth state
        bEnableDepthTest = self._cbEnableDepthTest.GetValue()
        bEnableDepthWrite = self._cbEnableDepthWrite.GetValue()
        depthStateHandle = Material.GetDepthStateProperty(self._materialHandle)
        MPDepthState.SetDepthState(depthStateHandle, bEnableDepthTest, bEnableDepthWrite)
        
        # material ambient
        bEnableAmbient = self._cbEnableAmbient.GetValue()
        color = self._colorMaterialAmbientColor.GetValue()
        r, g, b, a = map(lambda n : n / 255.0, (color.Red(), color.Green(), color.Blue(), color.Alpha()))
        materialAmbientHandle = Material.GetAmbientProperty(self._materialHandle)
        MPAmbient.SetAmbient(materialAmbientHandle, bEnableAmbient, r, g, b, a)
        
        # material diffuse
        bEnableDiffuse = self._cbEnableDiffuse.GetValue()
        color = self._colorMaterialDiffuseColor.GetValue()
        r, g, b, a = map(lambda n : n / 255.0, (color.Red(), color.Green(), color.Blue(), color.Alpha()))
        materialDiffuseHandle = Material.GetDiffuseProperty(self._materialHandle)
        MPDiffuse.SetDiffuse(materialDiffuseHandle, bEnableDiffuse, r, g, b, a)
            
        # material specular
        bEnableSpecular = self._cbEnableSpecular.GetValue()
        color = self._colorMaterialSpecularColor.GetValue()
        shiness = float(self._editMaterialSpecularShiness.GetValue())
        r, g, b, a = map(lambda n : n / 255.0, (color.Red(), color.Green(), color.Blue(), color.Alpha()))
        materialSpecularHandle = Material.GetSpecularProperty(self._materialHandle)
        MPSpecular.SetSpecular(materialSpecularHandle, bEnableSpecular, r, g, b, a, shiness)        
            
        self.EndModal(wx.ID_OK)
        
    """
    def __SaveMaterial(self, path, materialHandle):
            
        # write material file.
        impl = minixml.getDOMImplementation()
        newdoc = impl.createDocument(None, None, None)

        mtlElem = newdoc.createElement('Material')
        newdoc.childNodes.append(mtlElem)
        
        # texture mapping.
        mapCount = TextureMapping.GetMapCount(materialHandle)
        for i in xrange(0, mapCount):
            ret, texFileName = TextureMapping.GetMapTextureFile(materialHandle, i)
            ret, texName = TextureMapping.GetMapTextureName(materialHandle, i)
            tmElem = newdoc.createElement('TextureMapping')
            mtlElem.childNodes.append(tmElem)
            
            tmElem.setAttributeNode(newdoc.createAttribute('TextureFile'))
            tmElem.setAttribute('TextureFile', texFileName)
            
            tmElem.setAttributeNode(newdoc.createAttribute('TextureName'))
            tmElem.setAttribute('TextureName', texName)
            
        # alpha blend
        alphaBlendElem = newdoc.createElement('AlphaBlend')
        mtlElem.childNodes.append(alphaBlendElem)
        
        alphaBlendElem.setAttributeNode(newdoc.createAttribute('Enable'))
        alphaBlendElem.setAttribute('Enable', bEnableAlphaBlend)
        
        alphaBlendElem.setAttributeNode(newdoc.createAttribute('SrcBlend'))
        alphaBlendElem.setAttribute('SrcBlend', srcBlend)
        
        alphaBlendElem.setAttributeNode(newdoc.createAttribute('DestBlend'))
        alphaBlendElem.setAttribute('DestBlend', destBlend)
        
        # alpha test
        alphaTestElem = newdoc.createElement('AlphaTest')
        mtlElem.childNodes.append(alphaTestElem)
        
        alphaTestElem.setAttributeNode(newdoc.createAttribute('Enable'))
        alphaTestElem.setAttribute('Enable', bEnableAlphaTest)
        
        alphaTestElem.setAttributeNode(newdoc.createAttribute('Type'))
        alphaTestElem.setAttribute('Type', alphaTestType)
        
        alphaTestElem.setAttributeNode(newdoc.createAttribute('Ref'))
        alphaTestElem.setAttribute('Ref', alphaTestRef)
        
        # culling mode
        cullingModeElem = newdoc.createElement('CullingMode')
        mtlElem.childNodes.append(cullingModeElem)
        
        cullingModeElem.setAttributeNode(newdoc.createAttribute('Mode'))
        cullingModeElem.setAttribute('Mode', cullingMode)
        
        # depth state
        
        # material ambient
        
        # material diffuse
        
        # material specular

        newdoc.writexml(open(self._outputFile, 'w'),    newl = '\r\n', addindent = '    ', encoding = 'utf-8')
        newdoc.unlink()        
    """
    
    def __CreateUIRenderState(self):
        """ Create render state setting group UI """
        
        sbRenderState = wx.StaticBox(self, -1, TD.RENDER_STATE)
        sizerRenderState = wx.StaticBoxSizer(sbRenderState, wx.VERTICAL)
        
        sizerAlphaBlend = self.__CreateUIAlphaBlend()
        sizerAlphaTest = self.__CreateUIAlphaTest()
        sizerCullingMode = self.__CreateUICullingMode()
        sizerDepthState = self.__CreateUIDepthState()

        sizerRenderState.Add(sizerAlphaBlend, 0, wx.LEFT|wx.RIGHT, border = 5)
        sizerRenderState.Add(sizerAlphaTest, 0, wx.LEFT|wx.RIGHT, border =5)
        sizerRenderState.Add(sizerCullingMode, 0, wx.LEFT|wx.RIGHT, border = 5)
        sizerRenderState.Add(sizerDepthState, 0, wx.LEFT|wx.RIGHT, border = 5)
        
        return sizerRenderState
        
    def __CreateUIAlphaBlend(self):
        """ alpha blend """
        
        # enable alpha blend
        self._cbEnableAlphaBlend = wx.CheckBox(self, -1, TD.ENABLE_ALPHA_BLEND)
        
        # src blend parameter
        static = wx.StaticText(self, -1, TD.SRC_BLEND_PARAMETER)
        self._comboSrcBlend = wx.ComboBox(self, -1, style = wx.CB_DROPDOWN|wx.CB_READONLY)
        self._comboSrcBlend.Append(u'SRC_ALPHA')
        self._comboSrcBlend.Append(u'INV_SRC_ALPHA')
        
        sizerSrcBlend = wx.BoxSizer(wx.HORIZONTAL)
        sizerSrcBlend.Add(static, 0, wx.CENTER)
        sizerSrcBlend.Add(self._comboSrcBlend, 0, wx.ALL|wx.EXPAND)
        
        # dest blend parameter
        static = wx.StaticText(self, -1, TD.DEST_BLEND_PARAMETER)
        self._comboDestBlend = wx.ComboBox(self, -1, style = wx.CB_DROPDOWN|wx.CB_READONLY)
        self._comboDestBlend.Append(u'SRC_ALPHA')
        self._comboDestBlend.Append(u'INV_SRC_ALPHA')
        
        sizerDestBlend = wx.BoxSizer(wx.HORIZONTAL)
        sizerDestBlend.Add(static, 0, wx.CENTER)
        sizerDestBlend.Add(self._comboDestBlend, 0, wx.ALL|wx.EXPAND)
        
        sizerAlphaBlend = wx.BoxSizer(wx.HORIZONTAL)
        sizerAlphaBlend.Add(self._cbEnableAlphaBlend, 0, wx.LEFT|wx.CENTER, border = 5)
        sizerAlphaBlend.Add(sizerSrcBlend, 0, wx.ALL|wx.EXPAND, border = 5)
        sizerAlphaBlend.Add(sizerDestBlend, 0, wx.ALL|wx.EXPAND, border = 5)
        return sizerAlphaBlend
        
    def __CreateUIAlphaTest(self):
        """ alpha test """
        
        # enable alpha test
        self._cbEnableAlphaTest = wx.CheckBox(self, -1, TD.ENABLE_ALPHA_TEST)
        
        # alpha test type.
        static = wx.StaticText(self, -1, TD.ALPHA_TEST_TYPE)
        self._comboAlphaTestType = wx.ComboBox(self, -1, style = wx.CB_DROPDOWN|wx.CB_READONLY)
        self._comboAlphaTestType.Append(u'NEVER')
        self._comboAlphaTestType.Append(u'LESS')
        self._comboAlphaTestType.Append(u'EQUAL')
        self._comboAlphaTestType.Append(u'NOT_EQUAL')
        self._comboAlphaTestType.Append(u'LESS_EQUAL')
        self._comboAlphaTestType.Append(u'GREATER')
        self._comboAlphaTestType.Append(u'GREATER_EQUAL')
        self._comboAlphaTestType.Append(u'ALWAYS')
        
        sizerAlphaTestType = wx.BoxSizer(wx.HORIZONTAL)
        sizerAlphaTestType.Add(static, 0, wx.CENTER)
        sizerAlphaTestType.Add(self._comboAlphaTestType, 0, wx.ALL|wx.EXPAND)
        
        # alpha test ref
        static = wx.StaticText(self, -1, TD.ALPHA_TEST_REF)
        self._editAlphaTestRef = wx.TextCtrl(self, -1)
        sizerAlphaTestRef = wx.BoxSizer(wx.HORIZONTAL)
        sizerAlphaTestRef.Add(static, 0, wx.CENTER)
        sizerAlphaTestRef.Add(self._editAlphaTestRef, 0, wx.ALL|wx.EXPAND)
        
        sizerAlphaTest = wx.BoxSizer(wx.HORIZONTAL)
        sizerAlphaTest.Add(self._cbEnableAlphaTest, 0, wx.LEFT|wx.CENTER, border = 5)
        sizerAlphaTest.Add(sizerAlphaTestType, 0, wx.ALL|wx.EXPAND, border = 5)
        sizerAlphaTest.Add(sizerAlphaTestRef, 0, wx.ALL|wx.EXPAND, border = 5)
        return sizerAlphaTest
        
    def __CreateUICullingMode(self):
        """ culling mode """
        
        sizerCullingMode = wx.BoxSizer(wx.HORIZONTAL)
        static = wx.StaticText(self, -1, TD.CULLING_MODE)
        self._comboCullingMode = wx.ComboBox(self, -1, style = wx.CB_DROPDOWN|wx.CB_READONLY)
        self._comboCullingMode.Append(u'NONE')
        self._comboCullingMode.Append(u'CW')
        self._comboCullingMode.Append(u'CCW')
        
        sizerCullingMode.Add(static, 0, wx.CENTER, border = 5)
        sizerCullingMode.Add(self._comboCullingMode, 0, wx.ALL|wx.EXPAND, border = 5)
        
        return sizerCullingMode
        
    def __CreateUIDepthState(self):
        """ depth state """
        
        self._cbEnableDepthTest = wx.CheckBox(self, -1, TD.ENABLE_DEPTH_TEST)
        self._cbEnableDepthWrite = wx.CheckBox(self, -1, TD.ENABLE_DEPTH_WRITE)
        sizerDepthState = wx.BoxSizer(wx.HORIZONTAL)
        sizerDepthState.Add(self._cbEnableDepthTest, 0, wx.ALL|wx.EXPAND, border = 5)
        sizerDepthState.Add(self._cbEnableDepthWrite, 0, wx.ALL|wx.EXPAND, border = 5)
        return sizerDepthState
        
    def __CreateUIShaderConstant(self):
        """ Create shader constant setting group UI """
        
        sbShaderConstant = wx.StaticBox(self, -1, TD.SHADER_CONSTANT)
        sizerShaderConstant = wx.StaticBoxSizer(sbShaderConstant, wx.VERTICAL)
        
        sizerAmbient = self.__CreateUIAmbient()
        sizerDiffuse = self.__CreateUIDiffuse()
        sizerSpecular = self.__CreateUISpecular()
        sizerShaderConstant.Add(sizerAmbient, 0, wx.LEFT|wx.RIGHT, border = 5)
        sizerShaderConstant.Add(sizerDiffuse, 0, wx.LEFT|wx.RIGHT, border = 5)
        sizerShaderConstant.Add(sizerSpecular, 0, wx.LEFT|wx.RIGHT, border = 5)
        
        return sizerShaderConstant
        
    def __CreateUIAmbient(self):
        """ ambient """
        
        # enable.
        self._cbEnableAmbient = wx.CheckBox(self, -1, TD.ENABLE_MATERIAL_AMBIENT)

        # material ambient color
        static = wx.StaticText(self, -1, TD.MATERIAL_AMBIENT_COLOR)
        self._colorMaterialAmbientColor = wxColorPickButton(self, -1, '')
        sizerMaterialAmbientColor = wx.BoxSizer(wx.HORIZONTAL)
        sizerMaterialAmbientColor.Add(static, 0, wx.CENTER)
        sizerMaterialAmbientColor.Add(self._colorMaterialAmbientColor, 0, wx.ALL|wx.EXPAND)

        sizerMaterialAmbient = wx.BoxSizer(wx.HORIZONTAL)
        sizerMaterialAmbient.Add(self._cbEnableAmbient, 0, wx.CENTER|wx.LEFT|wx.RIGHT, border = 5)
        sizerMaterialAmbient.Add(sizerMaterialAmbientColor, 0, wx.CENTER|wx.LEFT|wx.RIGHT, border = 5)
        return sizerMaterialAmbient
        
    def __CreateUIDiffuse(self):
        """ diffuse """
 
         # enable.
        self._cbEnableDiffuse = wx.CheckBox(self, -1, TD.ENABLE_MATERIAL_DIFFUSE)

        # material diffuse color
        static = wx.StaticText(self, -1, TD.MATERIAL_DIFFUSE_COLOR)
        self._colorMaterialDiffuseColor = wxColorPickButton(self, -1, '')
        sizerMaterialDiffuseColor = wx.BoxSizer(wx.HORIZONTAL)
        sizerMaterialDiffuseColor.Add(static, 0, wx.CENTER)
        sizerMaterialDiffuseColor.Add(self._colorMaterialDiffuseColor, 0, wx.ALL|wx.EXPAND)
        
        sizerMaterialDiffuse = wx.BoxSizer(wx.HORIZONTAL)
        sizerMaterialDiffuse.Add(self._cbEnableDiffuse, 0, wx.CENTER|wx.LEFT|wx.RIGHT, border = 5)
        sizerMaterialDiffuse.Add(sizerMaterialDiffuseColor, 0, wx.CENTER|wx.LEFT|wx.RIGHT, border = 5)
        return sizerMaterialDiffuse
       
    def __CreateUISpecular(self):
        """ specular """
        
        # enable.
        self._cbEnableSpecular = wx.CheckBox(self, -1, TD.ENABLE_MATERIAL_SPECULAR)

        # material specular color
        static = wx.StaticText(self, -1, TD.MATERIAL_SPECULAR_COLOR)
        self._colorMaterialSpecularColor = wxColorPickButton(self, -1, '')
        sizerMaterialSpecularColor = wx.BoxSizer(wx.HORIZONTAL)
        sizerMaterialSpecularColor.Add(static, 0, wx.CENTER)
        sizerMaterialSpecularColor.Add(self._colorMaterialSpecularColor, 0, wx.ALL|wx.EXPAND)
        
        # material specular shiness
        static = wx.StaticText(self, -1, TD.MATERIAL_SPECULAR_SHINESS)
        self._editMaterialSpecularShiness = wx.TextCtrl(self, -1)
        sizerMaterialSpecularShiness = wx.BoxSizer(wx.HORIZONTAL)
        sizerMaterialSpecularShiness.Add(static, 0, wx.CENTER)
        sizerMaterialSpecularShiness.Add(self._editMaterialSpecularShiness, 0, wx.ALL|wx.EXPAND)
        
        sizerMaterialSpecular = wx.BoxSizer(wx.HORIZONTAL)
        sizerMaterialSpecular.Add(self._cbEnableSpecular, 0, wx.CENTER|wx.LEFT|wx.RIGHT, border = 5)
        sizerMaterialSpecular.Add(sizerMaterialSpecularColor, 0, wx.CENTER|wx.LEFT|wx.RIGHT, border = 5)
        sizerMaterialSpecular.Add(sizerMaterialSpecularShiness, 0, wx.CENTER|wx.LEFT|wx.RIGHT, border = 5)
        return sizerMaterialSpecular
        
    def UpdateUI(self, materialHandle):
        """ update UI from material handle """
        
        self._materialHandle = materialHandle
        
        # alpha blend
        alphaBlendHandle = Material.GetAlphaBlendProperty(materialHandle)
        bEnable, srcBlend, destBlend = MPAlphaBlend.GetAlphaBlend(alphaBlendHandle)
        self._cbEnableAlphaBlend.SetValue(bEnable)
        self._comboSrcBlend.SetSelection(srcBlend)
        self._comboDestBlend.SetSelection(destBlend)
        
        # alpha test
        alphaTestHandle = Material.GetAlphaTestProperty(materialHandle)
        bEnable, alphaTestType, ref = MPAlphaTest.GetAlphaTest(alphaTestHandle)
        self._cbEnableAlphaTest.SetValue(bEnable)
        self._comboAlphaTestType.SetSelection(alphaTestType)
        self._editAlphaTestRef.SetValue(str(ref))
        
        # culling mode
        cullingModeHandle = Material.GetCullingModeProperty(materialHandle)
        cullingMode = MPCullingMode.GetCullingMode(cullingModeHandle)
        self._comboCullingMode.SetSelection(cullingMode)
        
        # depth state
        depthStateHandle = Material.GetDepthStateProperty(materialHandle)
        bEnable, bWriteEnable = MPDepthState.GetDepthState(depthStateHandle)
        self._cbEnableDepthTest.SetValue(bEnable)
        self._cbEnableDepthWrite.SetValue(bWriteEnable)
        
        # material ambient
        ambientHandle = Material.GetAmbientProperty(materialHandle)
        bEnable, r, g, b, a = MPAmbient.GetAmbient(ambientHandle)
        r, g, b, a = map(lambda n : int(n * 255.0), (r, g, b, a))
        self._cbEnableAmbient.SetValue(bEnable)
        self._colorMaterialAmbientColor.SetValue(wx.Color(r, g, b, a))
        
        # material diffuse
        diffuseHandle = Material.GetDiffuseProperty(materialHandle)
        bEnable, r, g, b, a = MPDiffuse.GetDiffuse(diffuseHandle)
        r, g, b, a = map(lambda n : int(n * 255.0), (r, g, b, a))
        self._cbEnableDiffuse.SetValue(bEnable)
        self._colorMaterialDiffuseColor.SetValue(wx.Color(r, g, b, a))
        
        # material specular
        specularHandle = Material.GetSpecularProperty(materialHandle)
        bEnable, r, g, b, a, shiness = MPSpecular.GetSpecular(specularHandle)
        r, g, b, a = map(lambda n : int(n * 255.0), (r, g, b, a))
        self._cbEnableSpecular.SetValue(bEnable)
        self._colorMaterialSpecularColor.SetValue(wx.Color(r, g, b, a))
        self._editMaterialSpecularShiness.SetValue(str(shiness))
        
        
        